#include "RMTBSocketThread.h"
#pragma optimize("",off)
FRMTBSocketThread::FRMTBSocketThread(FString url, int32 port)
{
	{
		FScopeLock Lock(&mCritical);
		ServerURL = url;
		ServerPort = port;
	}
	Thread = FRunnableThread::Create(this, TEXT("RMTBSocketThread"), 4096, TPri_BelowNormal);

}

FRMTBSocketThread::~FRMTBSocketThread()
{
	if (Thread) {
		delete Thread;
		Thread = nullptr;
	}
}

bool FRMTBSocketThread::Init()
{
	
	FScopeLock Lock(&mCritical);
	SocketSubsystem= ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM);
	Socket= SocketSubsystem->CreateSocket(NAME_Stream, TEXT("RMTBSocket"));
	uint8 IP4Nums[4];
	if (!FormatIP4ToNumber(ServerURL,IP4Nums))
	{
		return false;
	}
	FIPv4Endpoint Endpoint(FIPv4Address(IP4Nums[0], IP4Nums[1], IP4Nums[2], IP4Nums[3]), ServerPort);
	Socket->Connect(*Endpoint.ToInternetAddr());
	UE_LOG(LogRMTBSocketThread, Warning, TEXT("Init Success"));
	return true;
}

uint32 FRMTBSocketThread::Run()
{
	while (true)
	{
// 		if (Socket->GetConnectionState()==ESocketConnectionState::SCS_Connected)
// 		{
// 			UE_LOG(LogRMTBSocketThread, Warning, TEXT("Init Success"));
// 		}
		RecvData();
		BroadcastMessage();
		trySendMessage();
	}
	return 0;
}
void FRMTBSocketThread::RecvData()
{
	uint32 Size = 0;
	if (Socket->HasPendingData(Size))
	{
		TArray<uint8> ReceivedData;
		ReceivedData.Init(0, Size);
		int32 Read = 0;
		Socket->Recv(ReceivedData.GetData(), ReceivedData.Num(), Read);
		if (Size>0)
		{
			FString ReceivedUE4String = StringFromBinaryArray(ReceivedData);
			//UE_LOG(LogRMTBSocketThread, Warning, TEXT("RecvData : %s"),*ReceivedUE4String);
			FScopeLock Lock(&mCritical);
			RecvMessage = ReceivedUE4String;
		}
	}
}

void FRMTBSocketThread::BroadcastMessage()
{
	FScopeLock Lock(&mCritical);
	if (RecvMessage.Len()>0)
	{
		OnMessage.Broadcast(RecvMessage);
		RecvMessage = "";
	}
}

void FRMTBSocketThread::trySendMessage()
{
	FScopeLock Lock(&mCritical);
	if (PeddingMessage.Len()>0)
	{
		int32 byteSend;
		Socket->Send((uint8*)TCHAR_TO_UTF8(*PeddingMessage), PeddingMessage.Len(), byteSend);
		PeddingMessage = "";
	}
}

FString FRMTBSocketThread::StringFromBinaryArray(TArray<uint8> BinaryArray)
{
	BinaryArray.Add(0);
	return FString(ANSI_TO_TCHAR(reinterpret_cast<const char*>(BinaryArray.GetData())));
}
void FRMTBSocketThread::Stop()
{

}

void FRMTBSocketThread::SendMessage(FString msg)
{
	FScopeLock Lock(&mCritical);
	PeddingMessage = msg;
}

bool FRMTBSocketThread::FormatIP4ToNumber(const FString& TheIP, uint8(&Out)[4])
{
	TheIP.Replace(TEXT(" "), TEXT(""));
	TArray<FString>Parts;
	TheIP.ParseIntoArray(Parts, TEXT("."), true);
	if (Parts.Num() != 4) {
		return false;
	}
	for (int32 i = 0; i < Parts.Num(); i++)
	{
		Out[i] = FCString::Atoi(*Parts[i]);
	}
	return true;
}

#pragma optimize("",on)